package com.ld.zookeeper.tools;

import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

/**
 * @author:ld
 * @create:2020-04-22 13:19
 * @description: 实现分布式唯一id
 * 1、通过顺序节点实现
 *  思路：
 *      1）开启多个线程同时创建id模拟并发场景
 *      2）创建id逻辑，动态创建临时顺序节点，获取节点路径，截取出顺序号作为唯一id
 *
 * 2、通过版本号实现(思路一样)
 */
public class ZookeeperID {

    //连接对象
    private ZooKeeper zooKeeper;

    //连接地址
    private final String IP = "127.0.0.1:2181";

    private CountDownLatch countDownLatch = new CountDownLatch(1);

    //根节点
    private final String ROOT_NODE = "/ids";

    //节点前缀
    private final String PREFIX_NODE = "/id";

    //节点数据
    private final String data = "";

    /**
     * 获取连接
     */
    public void getZookeeper(){
        try {
            zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                    //连接成功
                    if(Event.KeeperState.SyncConnected.equals(watchedEvent.getState())){
                        countDownLatch.countDown();
                        System.out.println("连接成功......");
                    }else if(Event.KeeperState.Disconnected.equals(watchedEvent.getState())){
                        System.out.println("连接失败......");
                    }else if(Event.KeeperState.AuthFailed.equals(watchedEvent.getState())){
                        System.out.println("用户认证失败......");
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        //等待连接成功
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭连接
     */
    public void close() throws InterruptedException {
        zooKeeper.close();
    }

    /**
     * 获取id
     */
    public void getId() {
        //创建临时顺序节点
        String node = null;
        try {
            node = zooKeeper.create(ROOT_NODE + PREFIX_NODE, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //截取id
        if(node != null){
            String id = node.substring((ROOT_NODE + PREFIX_NODE).length());
            System.out.println(Thread.currentThread().getName() + "----->" + id);
        }
    }

    /**
     * 开启多个线程池
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ZookeeperID zookeeperID = new ZookeeperID();
        //创建连接
        zookeeperID.getZookeeper();
        //开启线程创建id,模拟并发场景
        for (int i = 0;i < 10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int j = 0;j < 100;j++){
                        zookeeperID.getId();
                    }
                    countDownLatch.countDown();
                }
            }).start();
        }
        //等待所有线程执行完成，关闭zookeeper连接
        countDownLatch.await();
        zookeeperID.close();
    }
}
